﻿using gcloud_voice;
using UnityEngine;

namespace GVoiceSdk.GCloudVoiceAgent
{
    // 离线语音模块
    public static class OffLineVoiceAgent
    {
        public delegate void OnApplyMessageKeyComplete(bool succ, int completeCode);

        public delegate void OnDownloadRecordFileComplete(bool succ, string filePath, string fileID);

        public delegate void OnPlayRecordFileComplete(bool succ, string filePath);

        public delegate void OnSpeechToText(bool succ, string fileID, string result);

        public delegate void OnUploadReccordFileComplete(bool succ, string filePath, string fileID);

        private static IGCloudVoice m_voiceengine = null;

        // 申请语音消息key完成回调
        public static OnApplyMessageKeyComplete onApplyMessageKeyComplete;

        // 录音上传完成回调
        public static OnUploadReccordFileComplete onUploadReccordFileComplete;

        // 录音下载完成回调
        public static OnDownloadRecordFileComplete onDownloadRecordFileComplete;

        // 录音播放完成回调
        public static OnPlayRecordFileComplete onPlayRecordFileComplete;

        // 录音识别完成回调
        public static OnSpeechToText onSpeechToText;

        // 初始化
        public static void Init(IGCloudVoice voiceEngine)
        {
            m_voiceengine = voiceEngine;

            SubcribeCompleteEvents();
        }

        // 注册事件完成回调
        private static void SubcribeCompleteEvents()
        {
            m_voiceengine.OnApplyMessageKeyComplete += (GCloudVoiceCompleteCode code) =>
            {
                Debug.Log("OnApplyMessageKeyComplete c# callback , code := " + code.ToString());
                bool succ = (code == GCloudVoiceCompleteCode.GV_ON_MESSAGE_KEY_APPLIED_SUCC);
                if (onApplyMessageKeyComplete != null)
                {
                    onApplyMessageKeyComplete(succ, (int)code);
                }
            };

            m_voiceengine.OnUploadReccordFileComplete +=
                (GCloudVoiceCompleteCode code, string filepath, string fileid) =>
                {
                    Debug.Log("OnUploadReccordFileComplete c# callback , code := " + code.ToString() +
                              ", filepath := " + filepath + " fileid := " + fileid);
                    bool succ = (code == GCloudVoiceCompleteCode.GV_ON_UPLOAD_RECORD_DONE);
                    if (onUploadReccordFileComplete != null)
                    {
                        onUploadReccordFileComplete(succ, filepath, fileid);
                    }
                };

            m_voiceengine.OnDownloadRecordFileComplete +=
                (GCloudVoiceCompleteCode code, string filepath, string fileid) =>
                {
                    Debug.Log("OnDownloadRecordFileComplete c# callback , code := " + code.ToString() +
                              ", filepath := " + filepath + " fileid := " + fileid);
                    bool succ = (code == GCloudVoiceCompleteCode.GV_ON_DOWNLOAD_RECORD_DONE);
                    if (onDownloadRecordFileComplete != null)
                    {
                        onDownloadRecordFileComplete(succ, filepath, fileid);
                    }
                };

            m_voiceengine.OnPlayRecordFilComplete += (GCloudVoiceCompleteCode code, string filepath) =>
            {
                Debug.Log("OnPlayRecordFilComplete c# callback , code := " + code.ToString() + " , filepath : " +
                          filepath);
                bool succ = (code == GCloudVoiceCompleteCode.GV_ON_PLAYFILE_DONE);
                if (onPlayRecordFileComplete != null)
                {
                    onPlayRecordFileComplete(succ, filepath);
                }
            };

            m_voiceengine.OnSpeechToText += (GCloudVoiceCompleteCode code, string fileID, string result) =>
            {
                Debug.Log("OnSpeechToText c# callback , code := " + code.ToString() + " fileID := " + fileID +
                          " result := " + (null == result ? "<null>" : result));
                bool succ = (code == GCloudVoiceCompleteCode.GV_ON_STT_SUCC);
                if (onSpeechToText != null)
                {
                    onSpeechToText(succ, fileID, result);
                }
            };
        }


        /// <summary>
        ///     申请语音消息key,在语音消息的模式下，需要先申请许可才可以正常使用
        /// </summary>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool ApplyMessageKey()
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.ApplyMessageKey(60000);
            Debug.Log("GCloudVoiceSDK ApplyMessageKey , ret := " + ret.ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                return false;
            }

            return true;
        }


        /// <summary>
        ///     开始录音
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool StartRecording(string filePath)
        {
            if (m_voiceengine == null)
            {
                Debug.Log("[C#] OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.StartRecording(filePath);
            Debug.Log("[C#] GCloudVoiceSDK StartRecording , ret := " + ret + ",filePath: " + filePath);
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                if (ret == (int)GCloudVoiceErr.GCLOUD_VOICE_NEED_AUTHKEY && null != GCloudVoiceSDK.onError)
                {
                    GCloudVoiceSDK.onError((int)VoiceErrorRetCode.ApplyMessageKey,
                        "StartRecording_return_GCLOUD_VOICE_NEED_AUTHKEY");
                }

                if (ret == (int)GCloudVoiceErr.GCLOUD_VOICE_RECORDING_ERR) // 如果正在录音
                {
                    ret = m_voiceengine.StopRecording(); // 先停止
                    Debug.Log("try GCloudVoiceSDK StopRecording , ret := " + ret.ToString());
                    ret = m_voiceengine.StartRecording(filePath); // 再尝试启动录音(只尝试一次)
                    Debug.Log("retry GCloudVoiceSDK StartRecording , ret := " + ret.ToString());
                    if (ret == (int)GCloudVoiceErr.GCLOUD_VOICE_RECORDING_ERR)
                    {
                        m_voiceengine.StopRecording(); // 如果还是正在录音就停掉
                    }

                    return (ret == (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC);
                }

                return false;
            }

            return true;
        }

        /// <summary>
        ///     结束录音
        /// </summary>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool StopRecording()
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.StopRecording();
            Debug.Log("GCloudVoiceSDK StopRecording , ret := " + ret.ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                if (ret == (int)GCloudVoiceErr.GCLOUD_VOICE_NEED_AUTHKEY && null != GCloudVoiceSDK.onError)
                {
                    GCloudVoiceSDK.onError((int)VoiceErrorRetCode.ApplyMessageKey,
                        "StopRecording_return_GCLOUD_VOICE_NEED_AUTHKEY");
                }

                return false;
            }

            return true;
        }

        /// <summary>
        ///     上传录音
        /// </summary>
        /// <param name="filePath">录音文件路径</param>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool UploadRecord(string filePath)
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.UploadRecordedFile(filePath, 60000);
            Debug.Log("GCloudVoiceSDK UploadRecord , ret := " + ret.ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                if (ret == (int)GCloudVoiceErr.GCLOUD_VOICE_NEED_AUTHKEY && null != GCloudVoiceSDK.onError)
                {
                    GCloudVoiceSDK.onError((int)VoiceErrorRetCode.ApplyMessageKey,
                        "UploadRecord_return_GCLOUD_VOICE_NEED_AUTHKEY");
                }

                return false;
            }

            return true;
        }

        /// <summary>
        ///     下载录音
        /// </summary>
        /// <param name="fileID">录音文件ID</param>
        /// <param name="downloadedPath">录音文件下载路径</param>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool DownloadRecord(string fileID, string downloadedPath)
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.DownloadRecordedFile(fileID, downloadedPath, 60000);
            Debug.Log("GCloudVoiceSDK DownloadRecord , fileID := " + fileID + " , ret := " + ret.ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                if (ret == (int)GCloudVoiceErr.GCLOUD_VOICE_NEED_AUTHKEY && null != GCloudVoiceSDK.onError)
                {
                    GCloudVoiceSDK.onError((int)VoiceErrorRetCode.ApplyMessageKey,
                        "DownloadRecord_return_GCLOUD_VOICE_NEED_AUTHKEY");
                }

                return false;
            }

            return true;
        }

        /// <summary>
        ///     播放录音
        /// </summary>
        /// <param name="filePath">录音文件路径</param>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool PlayRecord(string filePath)
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.PlayRecordedFile(filePath);
            Debug.Log("GCloudVoiceSDK DownloadRecord , ret := " + ret.ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        ///     停止播放录音
        /// </summary>
        /// <param name="filePath">录音文件路径</param>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool StopPlayRecord()
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.StopPlayFile();
            Debug.Log("GCloudVoiceSDK StopPlayFile , ret := " + ret.ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                return false;
            }

            return true;
        }


        /// <summary>
        ///     识别录音
        /// </summary>
        /// <param name="fileID">录音文件ID，需要是在translation模式下录制得来的，不是message模式录制得来的</param>
        /// <returns>执行成功返回true, 执行失败返回false</returns>
        public static bool SpeechRecord(string fileID)
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return false;
            }

            int ret = m_voiceengine.SpeechToText(fileID);
            Debug.Log("GCloudVoiceSDK SpeechToText , fileID := " + fileID + " , ret := " + ret.ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                return false;
            }

            return true;
        }


        /// <summary>
        ///     获取录音的秒数
        /// </summary>
        /// <param name="filePath">录音文件路径</param>
        /// <returns>返回录音的秒数</returns>
        public static int GetRecordSecond(string filePath)
        {
            if (m_voiceengine == null)
            {
                Debug.Log("OffLineVoice.m_voiceengine is null");
                return 0;
            }

            int[] bytes = new int[1];
            bytes[0] = 0;

            float[] seconds = new float[1];
            seconds[0] = 0;

            int ret = m_voiceengine.GetFileParam(filePath, bytes, seconds);
            Debug.Log("GCloudVoiceSDK GetFileParam , filePath := " + filePath + " , ret := " + ret.ToString()
                      + " , bytes[0] := " + bytes[0].ToString() + " , seconds[0] := " + seconds[0].ToString());
            if (ret != (int)GCloudVoiceErr.GCLOUD_VOICE_SUCC)
            {
                return 0;
            }

            return (int)seconds[0];
        }
    }
}